home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / sbin / update-initramfs < prev    next >
Encoding:
Text File  |  2009-04-10  |  10.3 KB  |  551 lines

  1. #!/bin/sh
  2.  
  3. STATEDIR=/var/lib/initramfs-tools
  4. BOOTDIR=/boot
  5. CONF=/etc/initramfs-tools/update-initramfs.conf
  6. KPKGCONF=/etc/kernel-img.conf
  7. USETRIGGERS=true
  8. mode=""
  9. version=""
  10.  
  11. set -e
  12.  
  13. [ -r ${CONF} ] && . ${CONF}
  14.  
  15. if       $USETRIGGERS                        \
  16.     && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ]        \
  17.     && [ $# = 1 ]                         \
  18.     && [ x"$1" = x-u ]                    \
  19.     && dpkg-trigger --check-supported 2>/dev/null
  20. then
  21.     if dpkg-trigger --no-await update-initramfs; then
  22.         echo "update-initramfs: deferring update (trigger activated)"
  23.         exit 0
  24.     fi
  25. fi
  26.  
  27. usage()
  28. {
  29.     if [ -n "${1}" ]; then
  30.         printf "${@}\n\n" >&2
  31.     fi
  32.     cat >&2 << EOF
  33. Usage: ${0} [OPTION]...
  34.  
  35. Options:
  36.  -k [version]    Specify kernel version or 'all'
  37.  -c        Create a new initramfs
  38.  -u        Update an existing initramfs
  39.  -d        Remove an existing initramfs
  40.  -t        Take over a custom initramfs with this one
  41.  -b        Set alternate boot directory
  42.  -v        Be verbose
  43.  -h        This message
  44.  
  45. EOF
  46.     exit 1
  47. }
  48.  
  49. # chroot check
  50. chrooted()
  51. {
  52.         # borrowed from udev's postinst
  53.         if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
  54.                 # the devicenumber/inode pair of / is the same as that of
  55.                 # /sbin/init's root, so we're *not* in a chroot and hence
  56.                 # return false.
  57.                 return 1
  58.         fi
  59.         return 0
  60. }
  61.  
  62. mild_panic()
  63. {
  64.     if [ -n "${1}" ]; then
  65.         printf "${@}\n" >&2
  66.     fi
  67.     exit 0
  68. }
  69.  
  70. panic()
  71. {
  72.     if [ -n "${1}" ]; then
  73.         printf "${@}\n" >&2
  74.     fi
  75.     exit 1
  76. }
  77.  
  78. verbose()
  79. {
  80.     if [ "${verbose}" = 1 ]; then
  81.         printf "${@}\n"
  82.     fi
  83. }
  84.  
  85. version_exists()
  86. {
  87.     [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
  88.     return $?
  89. }
  90.  
  91. set_initramfs()
  92. {
  93.     initramfs="${BOOTDIR}/initrd.img-${version}"
  94. }
  95.  
  96.  
  97. # backup initramfs while running
  98. backup_initramfs()
  99. {
  100.     [ ! -r "${initramfs}" ] && return 0
  101.     initramfs_bak="${initramfs}.dpkg-bak"
  102.     [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
  103.     ln -f "${initramfs}" "${initramfs_bak}" \
  104.         || cp -a "${initramfs}" "${initramfs_bak}"
  105.     verbose "Keeping ${initramfs_bak}"
  106. }
  107.  
  108. # keep booted initramfs
  109. backup_booted_initramfs()
  110. {
  111.     initramfs_bak="${initramfs}.dpkg-bak"
  112.  
  113.     # first time run thus no backup
  114.     [ ! -r "${initramfs_bak}" ] && return 0
  115.  
  116.     # chroot with no /proc
  117.     [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
  118.  
  119.     # no kept backup wanted
  120.     [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
  121.  
  122.     # no backup yet
  123.     if [ ! -r "${initramfs}.bak" ]; then
  124.         mv -f ${initramfs_bak} "${initramfs}.bak"
  125.         verbose "Backup ${initramfs}.bak"
  126.         return 0
  127.     fi
  128.  
  129.     # keep booted initramfs
  130.     uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
  131.     if [ -n "$uptime_days" ]; then
  132.         boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
  133.     fi
  134.     if [ -n "${boot_initramfs}" ]; then
  135.         mv -f "${initramfs_bak}" "${initramfs}.bak"
  136.         verbose "Backup ${initramfs}.bak"
  137.         return 0
  138.     fi
  139.     verbose "Removing current backup ${initramfs_bak}"
  140.     rm -f ${initramfs_bak}
  141. }
  142.  
  143. # nuke generated copy
  144. remove_initramfs()
  145. {
  146.     [ -z "${initramfs_bak}" ] && return 0
  147.     rm -f "${initramfs_bak}"
  148.     verbose "Removing ${initramfs_bak}"
  149. }
  150.  
  151.  
  152. generate_initramfs()
  153. {
  154.     echo "update-initramfs: Generating ${initramfs}"
  155.     OPTS="-o"
  156.     if [ "${verbose}" = 1 ]; then
  157.         OPTS="-v ${OPTS}"
  158.     fi
  159.     if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
  160.         mv -f "${initramfs}.new" "${initramfs}"
  161.         set_sha1
  162.     else
  163.         mkinitramfs_return="$?"
  164.         remove_initramfs
  165.         rm -f "${initramfs}.new"
  166.         if [ "$mkinitramfs_return" = "2" ]; then
  167.             # minversion wasn't met, exit 0
  168.             exit 0
  169.         fi
  170.         echo "update-initramfs: failed for ${initramfs}"
  171.         exit $mkinitramfs_return
  172.     fi
  173. }
  174.  
  175. # lilo call
  176. run_lilo()
  177. {
  178.     # show lilo errors on failure
  179.     if ! lilo -t  > /dev/null 2>&1 ; then
  180.         echo "ERROR lilo fails for new ${initramfs}:"
  181.         echo
  182.         lilo -t
  183.     fi
  184.     lilo
  185. }
  186.  
  187. # check if lilo is on mbr
  188. mbr_check()
  189. {
  190.     # try to discover grub and be happy
  191.     [ -r /boot/grub/menu.lst ] \
  192.         && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
  193.             /boot/grub/menu.lst)
  194.     [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
  195.         && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
  196.     [ -n "${dev}" ] && [ -r ${dev} ] \
  197.         && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
  198.         | grep -q GRUB && return 0
  199.  
  200.     # check out lilo.conf for validity
  201.     boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
  202.     [ -z "${boot}" ] && return 0
  203.     case ${boot} in
  204.     /dev/md/*)
  205.         if [ -r /proc/mdstat ]; then
  206.             MD=${boot#/dev/md/}
  207.             boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
  208.             /proc/mdstat)"
  209.         fi
  210.         ;;
  211.     /dev/md*)
  212.         if [ -r /proc/mdstat ]; then
  213.             MD=${boot#/dev/}
  214.             boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
  215.             /proc/mdstat)"
  216.         fi
  217.         ;;
  218.     esac
  219.     [ ! -r "${boot}" ] && return 0
  220.     dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
  221.         && run_lilo && return 0
  222.  
  223.     # no idea which bootloader is used
  224.     echo
  225.     echo "WARNING: grub and lilo installed."
  226.     echo "If you use grub as bootloader everything is fine."
  227.     echo "If you use lilo as bootloader you must run lilo!"
  228.     echo
  229. }
  230.  
  231. # Invoke bootloader
  232. run_bootloader()
  233. {
  234.     # if both lilo and grub around, figure out if lilo needs to be run
  235.     if [ -x /sbin/grub ] || [ -e /boot/grub/menu.lst ] \
  236.     || [ -x /usr/sbin/grub ]; then
  237.         if [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  238.             [ -r "${KPKGCONF}" ] && \
  239.             do_b=$(awk  '/^do_bootloader/{print $3}' "${KPKGCONF}")
  240.             if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
  241.                 || [ "${do_b}" = "YES" ]; then
  242.                 run_lilo
  243.                 return 0
  244.             elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
  245.                 || [ "${do_b}" = "NO" ]; then
  246.                 return 0
  247.             else
  248.                 mbr_check
  249.                 return 0
  250.             fi
  251.         fi
  252.         return 0
  253.     fi
  254.     if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
  255.         run_lilo
  256.         return 0
  257.     fi
  258.     if [ -x /sbin/elilo ]; then
  259.         elilo
  260.         return 0
  261.     fi
  262.     if [ -r /etc/zipl.conf ]; then
  263.         zipl
  264.     fi
  265.     if flash-kernel --supported >/dev/null 2>&1; then
  266.         flash-kernel
  267.     fi
  268. }
  269.  
  270. compare_sha1()
  271. {
  272.     sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
  273.     return $?
  274. }
  275.  
  276. # Note that this must overwrite so that updates work.
  277. set_sha1()
  278. {
  279.     sha1sum "${initramfs}" > "${STATEDIR}/${version}"
  280. }
  281.  
  282. delete_sha1()
  283. {
  284.     rm -f "${STATEDIR}/${version}"
  285. }
  286.  
  287. # ro /boot is not modified
  288. ro_boot_check()
  289. {
  290.     # check irrelevant inside of a chroot
  291.     if [ ! -r /proc/mounts ] || chrooted; then
  292.         return 0
  293.     fi
  294.  
  295.     boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
  296.         && $2 == "/boot") print "ro"}' /proc/mounts)
  297.     if [ -n "${boot_opts}" ]; then
  298.         echo "WARNING: /boot is ro mounted."
  299.         echo "update-initramfs: Not updating ${initramfs}"
  300.         exit 0
  301.     fi
  302. }
  303.  
  304. get_sorted_versions()
  305. {
  306.     version_list=""
  307.  
  308.     for gsv_x in "${STATEDIR}"/*; do
  309.         gsv_x="$(basename "${gsv_x}")"
  310.         if [ "${gsv_x}" = '*' ]; then
  311.             return 0
  312.         fi
  313.         worklist=""
  314.         for gsv_i in $version_list; do
  315.             if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
  316.                 worklist="${worklist} ${gsv_x} ${gsv_i}"
  317.                 gsv_x=""
  318.             else
  319.                 worklist="${worklist} ${gsv_i}"
  320.             fi
  321.         done
  322.         if [ "${gsv_x}" != "" ]; then
  323.             worklist="${worklist} ${gsv_x}"
  324.         fi
  325.         version_list="${worklist}"
  326.     done
  327.  
  328.     verbose "Available versions: ${version_list}"
  329. }
  330.  
  331. set_current_version()
  332. {
  333.     if [ -f /boot/initrd.img-`uname -r` ]; then
  334.         version=`uname -r`
  335.     fi
  336. }
  337.  
  338. set_linked_version()
  339. {
  340.     if [ -L /initrd.img -a -e /initrd.img ]; then
  341.         linktarget="$(basename "$(readlink /initrd.img)")"
  342.     fi
  343.  
  344.     if [ -L /boot/initrd.img -a -e /boot/initrd.img ]; then
  345.         linktarget="$(basename "$(readlink /boot/initrd.img)")"
  346.     fi
  347.  
  348.     if [ -z "${linktarget}" ]; then
  349.         return
  350.     fi
  351.  
  352.     version="${linktarget##initrd.img-}"
  353. }
  354.  
  355. set_highest_version()
  356. {
  357.     get_sorted_versions
  358.     set -- ${version_list}
  359.     version=${1}
  360. }
  361.  
  362. create()
  363. {
  364.     if [ -z "${version}" ]; then
  365.         usage "Create mode requires a version argument"
  366.     fi
  367.  
  368.     set_initramfs
  369.  
  370.     if [ "${takeover}" = 0 ]; then
  371.         if version_exists "${version}"; then
  372.             panic "Cannot create version ${version}: already exists"
  373.         fi
  374.  
  375.         if [ -e "${initramfs}" ]; then
  376.             panic "${initramfs} already exists, cannot create."
  377.         fi
  378.     fi
  379.  
  380.     generate_initramfs
  381. }
  382.  
  383. update()
  384. {
  385.     if [ "${update_initramfs}" = "no" ]; then
  386.         echo "update-initramfs: Not updating initramfs."
  387.         exit 0
  388.     fi
  389.  
  390.     if [ -z "${version}" ]; then
  391.         set_linked_version
  392.     fi
  393.  
  394.     if [ -z "${version}" ]; then
  395.         set_highest_version
  396.     fi
  397.  
  398.     if [ -z "${version}" ]; then
  399.         set_current_version
  400.     fi
  401.  
  402.     if [ -z "${version}" ]; then
  403.         verbose "Nothing to do, exiting."
  404.         exit 0
  405.     fi
  406.  
  407.     set_initramfs
  408.  
  409.     ro_boot_check
  410.  
  411.     altered_check
  412.  
  413.     backup_initramfs
  414.  
  415.     generate_initramfs
  416.  
  417.     run_bootloader
  418.  
  419.     backup_booted_initramfs
  420. }
  421.  
  422. delete()
  423. {
  424.     if [ -z "${version}" ]; then
  425.         usage "Delete mode requires a version argument"
  426.     fi
  427.  
  428.     set_initramfs
  429.  
  430.     if [ ! -e "${initramfs}" ]; then
  431.         panic "Cannot delete ${initramfs}, doesn't exist."
  432.     fi
  433.  
  434.     if ! version_exists "${version}"; then
  435.         panic "Cannot delete version ${version}: Not created by this utility."
  436.     fi
  437.  
  438.     altered_check
  439.  
  440.     echo "update-initramfs: Deleting ${initramfs}"
  441.  
  442.     delete_sha1
  443.  
  444.     rm -f "${initramfs}"
  445. }
  446.  
  447. # Check for update mode on existing and modified initramfs
  448. altered_check()
  449. {
  450.     # No check on takeover
  451.     [ "${takeover}" = 1 ] && return 0
  452.     if [ ! -e "${initramfs}" ]; then
  453.         mild_panic "${initramfs} does not exist. Cannot update."
  454.     fi
  455.     if ! compare_sha1; then
  456.         echo "update-initramfs: ${initramfs} has been altered." >&2
  457.         mild_panic "update-initramfs: Cannot update. Override with -t option."
  458.     fi
  459. }
  460.  
  461. # Defaults
  462. verbose=0
  463. yes=0
  464. # We default to takeover=1 in Ubuntu, but not Debian
  465. takeover=1
  466.  
  467. ##
  468.  
  469. while getopts "k:cudyvtb:h?" flag; do
  470.     case "${flag}" in
  471.     k)
  472.         version="${OPTARG}"
  473.         ;;
  474.     c)
  475.         mode="c"
  476.         ;;
  477.     d)
  478.         mode="d"
  479.         ;;
  480.     u)
  481.         mode="u"
  482.         ;;
  483.     v)
  484.         verbose="1"
  485.         ;;
  486.     y)
  487.         yes="1"
  488.         ;;
  489.     t)
  490.         takeover="1"
  491.         ;;
  492.     b)
  493.         BOOTDIR="${OPTARG}"
  494.         if [ ! -d "${BOOTDIR}" ]; then
  495.             echo "Error: ${BOOTDIR} is not a directory."
  496.             exit 1
  497.         fi
  498.         ;;
  499.     h|?)
  500.         usage
  501.         ;;
  502.     esac
  503. done
  504.  
  505. # Validate arguments
  506. if [ -z "${mode}" ]; then
  507.     usage "You must specify at least one of -c, -u, or -d."
  508. fi
  509.  
  510. if [ "${version}" = "all" ] \
  511.     || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
  512.     : FIXME check for --yes, and if not ask are you sure
  513.     get_sorted_versions
  514.     if [ -z "${version_list}" ]; then
  515.         verbose "Nothing to do, exiting."
  516.         exit 0
  517.     fi
  518.  
  519.     OPTS="-b ${BOOTDIR}"
  520.     if [ "${verbose}" = "1" ]; then
  521.         OPTS="${OPTS} -v"
  522.     fi
  523.     if [ "${takeover}" = "1" ]; then
  524.         OPTS="${OPTS} -t"
  525.     fi
  526.     if [ "${yes}" = "1" ]; then
  527.         OPTS="${OPTS} -y"
  528.     fi
  529.     for u_version in ${version_list}; do
  530.         # Don't stop if one version doesn't work.
  531.         set +e
  532.         verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
  533.         "${0}" -${mode} -k "${u_version}" ${OPTS}
  534.         set -e
  535.     done
  536.     exit 0
  537. fi
  538.  
  539.  
  540. case "${mode}" in
  541.     c)
  542.         create
  543.         ;;
  544.     d)
  545.         delete
  546.         ;;
  547.     u)
  548.         update
  549.         ;;
  550. esac
  551.